#pragma once
#include <Windows.h>
#include <math.h>

#ifndef M_PI
#define M_PI 3.1415f
#endif

typedef float vec_t;
typedef vec_t vec3_t[3];
typedef vec_t vec4_t[4];

class Vector
{
public:
	Vector() { x = y = z = 0.0f; }
	Vector(float X, float Y, float Z) { x = X; y = Y; z = Z; }
	Vector(const Vector &v) { x = v.x; y = v.y; z = v.z; }

	float length() { return sqrt(x*x+y*y+z*z); }
	void subtract(Vector sub) { x-=sub.x; y -= sub.y; z -= sub.z; }
	float dotproduct(Vector dot) { return (x*dot.x+y*dot.y+z*dot.z); }
	Vector crossproduct(Vector v)
	{
		Vector res;

		res.x = y*v.z - z*v.y;
		res.y = z*v.x - x*v.z;
		res.z = x*v.y - y*v.x;

		return res;
	}
	void normalize() { float l = 1/length(); x *= l; y *= l; z *= l; }
	float vectodegree(Vector to) { return ((180.0f/3.1415f)*(asinf(dotproduct(to)))); }
	Vector RotateX(Vector in, float angle) { float a,c,s; Vector out; a = (float) (angle * M_PI/180); c = (float) cos(a); s = (float) sin(a); out.x = in.x; out.y = c*in.y - s*in.z; out.z = s*in.y + c*in.z; return out; }
	Vector RotateY(Vector in, float angle) { float a,c,s; Vector out; a = (float) (angle * M_PI/180); c = (float) cos(a); s = (float) sin(a); out.x = c*in.x + s*in.z; out.y = in.y; out.z = -s*in.x + c*in.z; return out; }
	Vector RotateZ(Vector in, float angle) { float a,c,s; Vector out; a = (float) (angle * M_PI/180); c = (float) cos(a); s = (float) sin(a); out.x = c*in.x - s*in.y; out.y = s*in.x + c*in.y; out.z = in.z; return out; }
	void nullvec() { x = y = z = 0; }

	void operator = (const float *farray) { x = farray[0]; y = farray[1]; z = farray[2]; }
	void operator = (const float &val) { x = y = z = val; }

	float operator [] (unsigned int element) { switch(element) { case 1: return y; case 2: return z; default: return x; } }

	Vector operator + (const Vector& add) const { return Vector(x+add.x,y+add.y,z+add.z); }
	void operator += (const Vector& add) { x += add.x; y += add.y; z += add.z; }
	Vector operator - (const Vector& sub) const	{ return Vector(x-sub.x,y-sub.y,z-sub.z); }
	void operator -= (const Vector& sub) { x -= sub.x; y -= sub.y; z -= sub.z; }
	Vector operator * (const float mul) const { return Vector(x*mul,y*mul,z*mul); }
	void operator *= (const float mul) { x *= mul; y *= mul; z *= mul; }
	Vector operator / (const float mul) const { return Vector(x/mul,y/mul,z/mul); }
	void operator /= (const float mul) { x /= mul; y /= mul; z /= mul; }

	bool operator == (const Vector& eqal) { return ((x == eqal.x) && (y == eqal.y) && (z == eqal.z)); }
	bool operator != (const Vector& eqal) { return ((x != eqal.x) && (y != eqal.y) && (z != eqal.z)); }
	bool operator > (const Vector& eqal) { return ((x > eqal.x) && (y > eqal.y) && (z > eqal.z)); }
	bool operator < (const Vector& eqal) { return ((x < eqal.x) && (y < eqal.y) && (z < eqal.z)); }
	bool operator >= (const Vector& eqal) { return ((x >= eqal.x) && (y >= eqal.y) && (z >= eqal.z)); }
	bool operator <= (const Vector& eqal) { return ((x <= eqal.x) && (y <= eqal.y) && (z <= eqal.z)); }

	float x;
	float y;
	float z;
};